//1.分治-归并排序-计算右侧小于当前元素的个数
class Solution {
public:
    vector<int> ret;
    vector<int> index;
    vector<int> tmpNums; 
    vector<int> tmpIndex; 
    void merge_sort(vector<int>& nums, int l, int r)
    {
        if(l == r) return;
        int mid = (l + r) >> 1;
        merge_sort(nums, l, mid);
        merge_sort(nums, mid + 1, r);
        int cur1 = l, cur2 = mid + 1, i = 0;
        while(cur1 <= mid && cur2 <= r)
        {
            if(nums[cur1] <= nums[cur2])
            {
                tmpNums[i] = nums[cur2];
                tmpIndex[i++] = index[cur2++]; 
            }
            else
            {
                ret[index[cur1]] += (r - cur2 + 1);
                tmpNums[i] = nums[cur1];
                tmpIndex[i++] = index[cur1++]; 
            }
        }
        while(cur1 <= mid)
        {
            tmpNums[i] = nums[cur1];
            tmpIndex[i++] = index[cur1++]; 
        }
        while(cur2 <= r)
        {
            tmpNums[i] = nums[cur2];
            tmpIndex[i++] = index[cur2++]; 
        }
        for(int i = l; i <= r; i++) 
        {
            nums[i] = tmpNums[i - l];
            index[i] = tmpIndex[i - l];
        }
    }

    vector<int> countSmaller(vector<int>& nums) {
        ret.resize(nums.size());
        index.resize(nums.size());
        tmpNums.resize(nums.size());
        tmpIndex.resize(nums.size());
        for(int i = 0; i < nums.size(); i++)
            index[i] = i;
        merge_sort(nums, 0, nums.size() - 1);    
        return ret;    
    }
};

//2.分治-归并排序-翻转对
//本题不能用归并排序的逻辑来计算翻转对的数量
//先用同向双指针统计完一左一右翻转对的数量之后再去合并两个有序数组
class Solution {
public:
    vector<int> tmp;
    int merge_sort(vector<int>& nums, int l, int r)
    {
        if(l == r) return 0;
        int mid = (l + r) >> 1;
        int ret = 0;
        ret += merge_sort(nums, l, mid);
        ret += merge_sort(nums, mid + 1, r);

        //统计一左一右翻转对的数量
        int cur1 = l, cur2 = mid + 1;
        while(cur1 <= mid && cur2 <= r)
        {
            if(nums[cur1] / 2.0 <= nums[cur2]) cur2++;
            else
            {
                ret += (r - cur2 + 1);
                cur1++;
            }
        }

        cur1 = l, cur2 = mid + 1;
        int i = 0;
        while(cur1 <= mid && cur2 <= r)
        {
            if(nums[cur1] <= nums[cur2]) tmp[i++] = nums[cur2++];
            else tmp[i++] = nums[cur1++];
        }
        while(cur1 <= mid) tmp[i++] = nums[cur1++];
        while(cur2 <= r) tmp[i++] = nums[cur2++];
        for(int i = l; i <= r; i++) nums[i] = tmp[i - l];
        return ret;
    }

    int reversePairs(vector<int>& nums) {
        tmp.resize(nums.size());
        return merge_sort(nums, 0, nums.size() - 1);  
    }
};
